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.
Clearer API, and easier to document. Let the user call `model.at(index)`