Added Binary Search for Sorted Collections

Added `search` method to collection prototype as per #3169. This is automatically used by `where` and `findWhere` when it is possible to do so to provide speedups without user needing to do anything.

For `toFind`, the user may provide:
- a comparison function which compares takes one value and returns 1 if the sought value has higher index, -1 if its lower and 0 if the value matches (`comparator` unused)
- a value to search for (the value of the `model[comparator]` sought - requires `comparator` to be a string)
- a model to search for (where `comparator` is a function)

Users may also request that it is the index of the model that is returned or that the model of highest/lowest index which matches the comparison is sought.

When no match is found, `undefined` is returned, or if `returnIndex` is true then `-1` is returned instead.

One point that may need to be considered is that the behaviour when a model is input as `toFind` but the `comparator` is a string is different from that when `comparator` is a function. Furthermore, the name of this method may also need some more thought to emphasise that it is for *binary* searches or that it only works on sorted collections so `binarySearch` or the more user-friendly `sortedSearched` might be preferable.
Well no, if the collection isn't sorted then it isn't sorted. I suppose you could allow this to pass in the case that the user has sorted the collection himself. I believe the thinking behind the `_.isFunction(toFind)` case was that if you were, *for example*, looking for a model who had a timestamp within a certain range (say a week or day) in a collection sorted by the timestamps property.