function uniq(array, isSorted, callback, thisArg) {
    var result = [];
    if (!array) {
      return result;
    }
    var computed,
        index = -1,
        length = array.length,
        seen = [];

    // juggle arguments
    if (typeof isSorted == 'function') {
      thisArg = callback;
      callback = isSorted;
      isSorted = false;
    }
    if (!callback) {
      callback = identity;
    } else if (thisArg) {
      callback = iteratorBind(callback, thisArg);
    }
    while (++index < length) {
      computed = callback(array[index], index, array);
      if (isSorted
            ? !index || seen[seen.length - 1] !== computed
            : indexOf(seen, computed) < 0
          ) {
        seen.push(computed);
        result.push(array[index]);
      }
    }
    return result;
  }
Creates a duplicate-value-free version of the `array` using strict equality
for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
for `isSorted` will run a faster algorithm. If `callback` is passed, each
element of `array` is passed through a callback` before uniqueness is computed.
The `callback` is bound to `thisArg` and invoked with 3 arguments; (value, index, array).

@static
@memberOf _
@alias unique
@category Arrays
@param {Array} array The array to process.
@param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
@param {Function} [callback=identity] The function called per iteration.
@param {Mixed} [thisArg] The `this` binding for the callback.
@returns {Array} Returns a duplicate-value-free array.
@example

_.uniq([1, 2, 1, 3, 1]);
// => [1, 2, 3]

_.uniq([1, 1, 2, 2, 3], true);
// => [1, 2, 3]

_.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
// => [1, 2, 3]

_.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
// => [1, 2, 3]