function flatten(array, isShallow, callback, thisArg) {
      // juggle arguments
      if (typeof isShallow != 'boolean' && isShallow != null) {
        thisArg = callback;
        callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
        isShallow = false;
      }
      if (callback != null) {
        array = map(array, callback, thisArg);
      }
      return baseFlatten(array, isShallow);
    }
Flattens a nested array (the nesting can be to any depth). If `isShallow`
is truey, the array will only be flattened a single level. If a callback
is provided each element of the array is passed through the callback before
flattening. The callback is bound to `thisArg` and invoked with three
arguments; (value, index, array).

If a property name is provided for `callback` the created "_.pluck" style
callback will return the property value of the given element.

If an object is provided for `callback` the created "_.where" style callback
will return `true` for elements that have the properties of the given object,
else `false`.

@static
@memberOf _
@category Arrays
@param {Array} array The array to flatten.
@param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
@param {Function|Object|string} [callback=identity] The function called
 per iteration. If a property name or object is provided it will be used
 to create a "_.pluck" or "_.where" style callback, respectively.
@param {*} [thisArg] The `this` binding of `callback`.
@returns {Array} Returns a new flattened array.
@example

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

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

var characters = [
  { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
  { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
];

// using "_.pluck" callback shorthand
_.flatten(characters, 'pets');
// => ['hoppy', 'baby puss', 'dino']