Edit in JSFiddle

$(function(){
  $.extend($.easing, {
      def: 'easeInSine',
      easeInSine: function (x, t, b, c, d) {
          return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
      },
      easeInOutBack: function (x, t, b, c, d, s) {
          if (s == undefined) s = 1.70158;
          if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
          return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
      }
  });

  var $slider = $('.slider')
    , slider_width = 0
    , $slider_inner = $slider.children().first()
    , $elements = $slider_inner.children('.element')
    , elements_count = $elements.length
    , element_width = $elements.first().width()
    , element_margin = 0
    , elements_fit = 0
    , visible_width = 0
    , vertical_max = 30 // max vertical deviation

  function onResize() {
    slider_width = $slider.width()
    elements_fit = Math.floor(slider_width/element_width)
    // we have a limited number of elements
    if (elements_fit > elements_count) {
      elements_fit = elements_count
    }
    // we need only odd number
    if (elements_fit % 2 === 0) {
      elements_fit -= 1
    }

    // find element margin for balancing
    element_margin = Math.ceil((slider_width - (element_width * elements_fit))/(elements_fit * 2))

    // set container width * 1.5 to fit clonned elements when scroll
    visible_width = (element_width + element_margin * 2) * elements_fit
    $slider_inner.width(Math.ceil(visible_width * 1.5))
    // add margins
    $elements.css({'margin-left': element_margin + 'px', 'margin-right': element_margin + 'px'})

    // set active element
    $elements.removeClass('active')
    $elements.slice(Math.floor(elements_fit/2), Math.floor(elements_fit/2) + 1).addClass('active')
  }

  function goTo(index_to) {
    var index_past = Math.floor(elements_fit/2)
    // if active element
    if (index_to === index_past) {
      return
    }

    var index_diff = index_to - index_past
      , $elements_slice
      , left_to = 0
      , i
      , visible_center = Math.floor((visible_width - element_width - element_margin * 2)/2)
      , margin_top = 0

    if (index_diff > 0) {
      $elements_slice = $elements.slice(0, index_diff)
      // append diff elements
      $elements_slice.clone().appendTo($slider_inner)
      // compute left offset
      left_to = -((element_width + element_margin * 2) * index_diff)
    } else {
      $elements_slice = $elements.slice(index_diff)
      // append diff elements
      $elements_slice.clone().prependTo($slider_inner)
      // set left offset
      $slider_inner.css('left', (element_width + element_margin * 2) * index_diff + 'px')
    }

    // reindex elements
    $elements = $slider_inner.children('.element')

    // scroll to position
    $slider_inner.animate({
      left: left_to + 'px'
    }, {
      duration: 1000
    , easing: 'easeInOutBack'
    , step: function(animation_diff) {
        for (i = $elements.length - 1; i >= 0; i--) {
          margin_top = Math.abs((visible_center - $elements[i].offsetLeft + 21 - animation_diff)/visible_center)

          // Apply easing to create curved shape
          margin_top = Math.max(0, Math.round(vertical_max - $.easing.easeInSine(0, margin_top, 0, vertical_max, 1)))

          $elements.slice(i, i+1).css('margin-top', margin_top == 0 ? 0 : margin_top + 'px')
        }
      }
    , complete: function() {
        // remove duplicates
        $elements_slice.remove()
        // reposition slider
        $slider_inner.css('left', 0)
        // reindex elements
        $elements = $slider_inner.children('.element')

        // set active element
        $elements.removeClass('active')
        $elements.slice(Math.floor(elements_fit/2), Math.floor(elements_fit/2) + 1).addClass('active')
      }
    })

  }

  onResize()
  goTo(0) // move it to align vertically

  $(window).on('resize', onResize)

  $slider
    .on('click', 'a.slider-control', function(ev){
      ev.preventDefault()
      var direction = $(this).hasClass('left') ? -1 : 1

      goTo(Math.floor(elements_fit/2) + direction)
    })
    .on('click', '.element', function(ev){
      ev.preventDefault()

      goTo($elements.index(this))
    })
})