Here is a solution ...

    // First create your array of terms
	$terms = array(
	  'level1-1' => array(
	    'level2-1' => array(
	      'level3' => array(),
	    ),
	    'level2-2' => array(
	      'level3' => array(
	        'level4' => array(),
	      ),
	    ),
	  ),
	);
	
    // Create your vocabulary.
    // First check if the vocabulary exists otherwise an error will be thrown when trying to create it.
	$vocabs = taxonomy_get_vocabularies(NULL);
	$vocab = new stdClass();
	foreach ($vocabs as $vocab_object) {
		if ($vocab_object->machine_name == 'vocab_short_name') {
            // Vocab found.  Grab the object.
			$vocab = $vocab_object;
			break;
		}
	}
    // If the vid is not set then create the vocab.
	if(!isset($vocab->vid)) {
		$vocab = new stdClass();
		$vocab->name = 'Vocabulary Name';
		$vocab->machine_name = 'vocab_short_name';
		taxonomy_vocabulary_save($vocab);
	}
    // Recursive function that will create the hierarchical terms.
	mymodule_add_hierarchical_terms($terms, $vocab->vid);

    
    function mymodule_add_hierarchical_terms($vocab, $vid, $parent = null) {
	
	  foreach($vocab as $term_name => $term) {
        // Create the term
		$term_object = new stdClass();
		$term_object->vid = $vid;
		$term_object->name = $term_name;
		if(isset($parent)) {
			$term_object->parent = $parent;
		}
		taxonomy_term_save($term_object);
		
		if(is_array($term)) {
          // Recursively call the function, passing the term id of the parent.
		  mymodule_add_hierarchical_terms($term, $vid, $term_object->tid);
		}
	  }
    }