Это знает не delete, а конкретный компилятор.
Как правило, оператор new для массивов выделяет чуть больше памяти, чем нужно. Возвращая пользователю адрес с некоторым смещением.
Таким образом, первые некоторое количество байт хранят служебную информацию о блоке.
Когда компилятор встречает delete[], он отматывает от адреса эти несколько байт назад, и извлекает служебную информацию. После чего он уже знает как именно нужно удалять блок.
Пользователи могут получать доступ к служебным данным, при помощи функций-расширений от компилятора.
Например, для компиляторов от вижал-студии, размер выделенного блока можно узнать вот так:
http://msdn.microsoft.com/en-us/library/z2s077bc.aspx